package core;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.UUID;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Entity{
	Graph graph;
	public UUID id;
	public String name;
	
	Node node;
	public HashSet<Node> nodesImplTo = new HashSet<Node>();
	
	String db_url;
	HashMap<String,String> varList;

	ArrayList<Process> procIn = new ArrayList<Process>();
	ArrayList<Process> procOut = new ArrayList<Process>();
	
	public ArrayList<HashMap<String,String>> tokenPool = new ArrayList<HashMap<String,String>>(); // 初始化和最后取出Token用
	
	public Entity(Graph g, String name){
		id = UUID.randomUUID();
		graph = g;
		graph.addEntity(this);
		db_url = "";
		this.name = name;
		varList = new HashMap<String,String>();
	}
	
	public Entity(Graph g, String name, HashMap<String,String> vars){
		id = UUID.randomUUID();
		graph = g;
		db_url = "";
		this.name = name;
		varList = vars;
	}
	
	public void addVariable(String name,String type){
		this.varList.put(name, type);
	}
	
	public void assign(Node node){
		this.node = node;
		this.db_url = node.DBUrl;
	}
	
	public void implTo(Node node){
		if(!node.loadEntity(this.toJSONObject()))
			log(name,"implTo()",false);
	}
	
	public void addProcIn(Process p){
		this.procIn.add(p);
	}
	
	public void addProcOut(Process p){
		this.procOut.add(p);
	}
	
	public void addToken(HashMap<String,String> token){
		tokenPool.add(token);
	}
	
	public void putTokens(){
		JSONArray tokensArray = new JSONArray();
		for(HashMap<String,String> token : tokenPool){
			tokensArray.put(token);
		}
		tokenPool.clear();
		if(!node.putTokens(id.toString(), tokensArray))
			log(name,"putTokens()",false);
	}
	
	public int getRemoteTokenNum(){
		try{
			return node.getTokenNum(id.toString());
		} catch (Exception ex){
			log(name,"getTokenNum()",false);
		}
		return 0; // Default value: 0
	}
	
	public void putTokens(ArrayList<HashMap<String,String>> tokens){
		JSONArray tokensArray = new JSONArray();
		for(HashMap<String,String> token : tokens){
			tokensArray.put(token);
		}
		if(!node.putTokens(id.toString(), tokensArray))
			log(name,"putTokens()",false);
	}
	
	public JSONArray getResult(){
		JSONArray result = node.getAllTokens(id.toString());
		return result;
	}
	
	public void unload(){
		
		for(Node node: nodesImplTo){
			if(!node.unloadEntity(id.toString()))
				log(name,"unload@"+node.ip,false);
		}
	}
	
	public void unloadFrom(Node node){
		
		if(!node.unloadEntity(id.toString()))
			log(name,"unload@"+node.ip,false);
	}

	// For Implement in remote ComputeNode
	public JSONObject toJSONObject(){
		JSONObject entity = new JSONObject();
		
		try {
			entity.put("id", id.toString());
			entity.put("name", name);
			entity.put("graph_id", graph.id);
			entity.put("DBUrl", db_url);
			entity.put("username", "");
			entity.put("passwd", "");
			entity.put("varList", varList);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		
		return entity;
	}
	
	static void log(String id, String func, boolean b){
		System.out.println("Entity: "+id+" "+func+" "+b);
	}
}
